Формат объектного файла.

Объектный файл имеет теговую структуру.
    Номинально, порядок блоков не имеет значения. Однако программа создаёт
объектный файл, в котором блоки располагаются в следующей последовательности:
1. Блок идентификатор
2. Блок данных
3. Блок глобальных меток
4. Блок локальных меток (если есть)
5. Блок ссылок на метки

Каждый блок имеет заголовок следующего формата:
{
    OBJTags  nHdrTag;       // Тэг заголовка
    OBJTags  nBlockTag;     // Тэг блока
    uint32_t nBlkLen;       // Размер данных блока (не включая размер заголовка)
    uint32_t nEntryCount;   // Количество элементов в блоке
    uint32_t nCheckSum;     // Контрольная сумма блока (на данный момент не
                            // используется и == 0)
}

Тэг заголовка
    Это константное значение, по которому определяется, что это действительно
заголовок и остальные поля имеют смысл. Оно одинаково для всех блоков.

Тэг блока
    Константное значение, по которому определяется тип блока. И как
интерпретировать данные блока.

Размер данных блока
    Размер данных блока байтах, следующих следом за заголовком.

Количество элементов в блоке
    Количество элементов данных блока. Например, количество меток в таблице.

Контрольная сумма блока
    Не используется, должна быть 0. Может быть когда-нибудь потом будет
использоваться.


    За заголовком блока следуют данные. В каждом блоке они интерпретируются
по своему.

Блок идентификатор
    Имеет данные следующей структуры:
{
    uint32_t nVersion;      // Версия объектного файла
    int16_t nStartAddress;  // Адрес компоновки по умолчанию объектного модуля.
    int16_t nMode;          // Режим компоновки
}
    В заголовке этого блока - количество элементов == 1, а размер данных == 8 (на данный момент)

Версия объектного файла
    На данный момент - число 0x1001

Адрес компоновки по умолчанию объектного модуля
    По умолчанию, это число 01000. Или адрес, заданный псевдокомандой .LA, или
ключом -s.
    Этот адрес используется пои линковке командой LI. Для первого объектного
файла, если адрес не задан явно ключом -s, берётся адрес компоновки из заголовка.
Для последующих объектных файлов - берётся текущий адрес компоновки, полученный
после компоновки предыдущего объектного файла, это как правило, адрес первого
слова за концом получающегося скомпонованного массива программы.


Режим компоновки
    Определяет стратегию обработки меток.
    Имеет три значения:
    -1 - объектный модуль скомпилирован в режиме CL, т.е. ещё не скомпонован и
полностью перемещаем.
    При линковке такого файла все метки корректируются в соответствии с базовым
адресом линковки модуля.
    1 и 0 - объектный модуль скомпилирован в режиме CO. Т.е. он скомпонован с
некоего определённого адреса и в него уже подставлены значения меток.
    При линковке такого файла, корректировать метки не имеет смысла, т.к. они
при этом станут некорректны. Поэтому они добавляются в результирующую таблицу
меток как есть.
    Вообще смысл линковки таких модулей имеет смысл либо если этот модуль идёт
первым, либо, если в последствии массив данных этого модуля будет перемещён на
заданный адрес, с которого он был скомпонован, программой пользователя.


Блок данных
    Содержит собственно бинарный массив сформированного кода.
    В заголовке этого блока - количество элементов == 1, а размер данных - 
размер полученного кода.


Блок глобальных меток
    Содержит таблицу глобальных меток объектного модуля.
    В заголовке этого блока - количество элементов - количество меток, а размер
данных - размер всего массива таблицы меток в байтах.

Структура одного элемента метки:
{
    uint32_t OBJTags::OBJ_Label;    // Тэг элемента метки
    uint32_t len                    // Длина строки имени метки
    uint8_t[len] label_text;        // Строка имени метки в unicode
    uint32_t value                  // Значение метки
    uint32_t type                   // Тип метки
}

Тэг элемента метки
    Константное значение, по которому определяется, что далее следует верный
набор данных метки.

Длина строки имени метки
    Размер строки текста в знаках. Значение может быть от 1 до 2^32-1, т.е.
длина имени может достигать 2 Гб, думаю этого более, чем достаточно.

Строка имени метки в unicode
    Собственно имя метки. Строка не содержит заключающего нуля, т.к. перед ней
имеется размер строки.

Значение метки
    Это адрес, где метка была определена. Фактически - это смещение от начала
кода. И чтобы получить фактическое значение, к нему надо прибавить адрес
компоновки по умолчанию.

Тип метки
    Различается всего два вида глобальных меток: Метка и Константа (присваивание)
Они обрабатываются по разному. Метку можно релоцировать, константу - нет.
Так же в типе метки содержатся некоторые флаги операций над метками, это нужно
для арифметических операций над метками.


Блок локальных меток
    По своей структуре совершенно идентичен блоку глобальных меток. Вся разница
лишь в том, что при определении глобальной метки, вся таблица локальных меток
обнуляется. И в объектный файл записывается либо пустая таблица, либо остаточная
таблица на момент окончания компиляции. 


Блок ссылок на метки
    По своей структуре так же идентичен блоку определений меток, разница лишь в
том, что в поле "Значение метки" содержится относительный адрес, где встретилась
ссылка на заданную метку. А в поле "Тип метки" содержатся свои типы для ссылок.

